﻿using Microsoft.Vbe.Interop;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VBACodeingTool
{
    public class CodeDataManager
    {
        private Dictionary<string, List<ProjectCodeData>> codeProjectData = new Dictionary<string, List<ProjectCodeData>>();
        private List<ProjectCodeData> showCodeData = new List<ProjectCodeData>();
        private List<ProjectCodeData> resultCodeData = new List<ProjectCodeData>();

        public CodeDataManager(Dictionary<string, List<ProjectCodeData>> codeProjectData)
        {
            CodeProjectData = codeProjectData;
        }

        public Dictionary<string, List<ProjectCodeData>> CodeProjectData { get => codeProjectData; set => codeProjectData = value; }
        public List<ProjectCodeData> ShowCodeData { get => showCodeData; set => showCodeData = value; }
        private List<ProjectCodeData> ResultCodeData { get => resultCodeData; set => resultCodeData = value; }

        public List<ProjectCodeData> GetShowCodeData(string input)
        {
            ResultCodeData.Clear();
            SearchProjectCodeData(input);
            if (ResultCodeData.Count < 0)
            {
                return new List<ProjectCodeData>();
            }
            ShowCodeData =
                (from codeData in ResultCodeData
                 orderby codeData.Score descending
                 select codeData).ToList();
            return ShowCodeData;
        }

        public void UpData(string name, List<ProjectCodeData> projectCodeDatas)
        {
            if (CodeProjectData.ContainsKey(name))
            {
                CodeProjectData[name] = projectCodeDatas;
            }
        }

        private void SearchProjectCodeData(string input)
        {
            string name = VBEHelper.GetCurrentCodeModule().Name;
            int line = VBEHelper.GetCodeAndPosition().Position.startRow;
            vbext_ProcKind vbext_ProcKind = vbext_ProcKind.vbext_pk_Proc;
            string currentSub = VBEHelper.GetCurrentCodeModule().ProcOfLine[line, out vbext_ProcKind];
            foreach (List<ProjectCodeData> codeDatas in codeProjectData.Values)
            {
                foreach (ProjectCodeData codeData in codeDatas)
                {
                    if (IsRule(codeData, name, currentSub))
                    {
                        SelectedCodeData(codeData, input);
                    }
                }
            }
        }

        private void SelectedCodeData(ProjectCodeData codeData, string input)
        {
            if (codeData.GetScore(input) > 40+((input.Length-3)*10))
            {
                ResultCodeData.Add(codeData);
            }
        }

        private bool IsRule(ProjectCodeData codeData, string name,string indexSub)
        {
            if (indexSub == codeData.Content)
            {
                return false;
            }
            if (name != codeData.ParentName && codeData.ScopeType == ScopeType._Private)
            {
                return false;
            }
            ParentType parentType = CodeLoaderHelper.ConvertParentType(VBEHelper.GetCurrentComponent().Type);
            switch (parentType)
            {
                case ParentType._Module:
                    if (codeData.ParentType != ParentType._Module)
                    {
                        return false;
                    }
                    break;

                case ParentType._Class:
                    if (codeData.ParentType == ParentType._Document)
                    {
                        return false;
                    }
                    if (name != codeData.ParentName && ParentType._Class == codeData.ParentType)
                    {
                        return false;
                    }
                    break;

                case ParentType._Document:
                    if (codeData.ParentType == ParentType._Class)
                    {
                        return false;
                    }
                    if (name != codeData.ParentName && ParentType._Document == codeData.ParentType)
                    {
                        return false;
                    }
                    break;

                case ParentType._NoType:
                    return false;

                default:
                    return false;
            }
            return true;
        }
    }
}